package services

import (
	"context"
	"github.com/golang/protobuf/ptypes/empty"
	"github.com/golang/protobuf/ptypes/wrappers"
	"sync"
	"time"

	"kop/framework/errors"
	"kop/pb"

	context2 "kop/framework/context"
	buildingC "kop/modules/building/client"
	captainC "kop/modules/captain/client"
	moneyC "kop/modules/money/client"
	questC "kop/modules/quest/client"
)

type BuildingService struct {
	context2.Context
	clicks sync.Map
}

// 点击加银币
func (s *BuildingService) Click(ctx context.Context, req *pb.BuildingClickRequest) (*pb.Money, error) {

	var roleID = s.GetRoleID(ctx)

	var clickTime int64
	if v, ok := s.clicks.Load(roleID); ok {
		clickTime = v.(int64)
	}

	var now = time.Now().UnixNano()
	if (now-clickTime)/1000/1000 < 100 {
		return &pb.Money{}, errors.Ignore
	}

	if req.Number > 2 {
		return &pb.Money{}, errors.ParamError
	}

	s.clicks.Store(roleID, now)

	// quest & daily quest
	questC.Click(roleID, int64(req.Number))
	questC.DailyQuestClick(roleID, int64(req.Number))

	var coin = buildingC.GetHall(roleID).Coin * int64(req.Number)
	return moneyC.AddCoin(roleID, coin), nil
}

// 升级建筑
func (s *BuildingService) LevelUp(ctx context.Context, req *wrappers.Int32Value) (*pb.BuildingLevelUpReply, error) {

	return buildingC.BuildingService.LevelUp(ctx, req)
}

// 升级大厅
func (s *BuildingService) HallLevelUp(ctx context.Context, req *empty.Empty) (*pb.HallLevelUpReply, error) {

	return buildingC.BuildingService.HallLevelUp(ctx, req)
}

// 增加水手
func (s *BuildingService) AddSeaman(ctx context.Context, req *pb.AddSeamanRequest) (*pb.AddSeamanResp, error) {

	return buildingC.BuildingService.AddSeaman(ctx, req)
}

// 设置海盗船船长
func (s *BuildingService) SetSeat(ctx context.Context, req *pb.APISetSeatRequest) (*pb.APISetSeatReply, error) {

	var reply pb.APISetSeatReply

	if req.BuildingID < 1 {
		return &reply, errors.ParamError
	}

	if req.BuildingSeat < 1 || req.BuildingSeat > 5 {
		// 位置只能1~5之间
		return &reply, errors.ParamError
	}

	var roleID = s.GetRoleID(ctx)

	building := buildingC.GetBuilding(roleID, req.BuildingID)

	switch req.CaptainID {
	case building.Captain1:
		if req.BuildingSeat == 1 {
			return &reply, nil
		}

		building.Captain1 = 0

	case building.Captain2:
		if req.BuildingSeat == 2 {
			return &reply, nil
		}

		building.Captain2 = 0

	case building.Captain3:
		if req.BuildingSeat == 3 {
			return &reply, nil
		}

		building.Captain3 = 0

	case building.Captain4:
		if req.BuildingSeat == 4 {
			return &reply, nil
		}

		building.Captain4 = 0

	case building.Captain5:
		if req.BuildingSeat == 5 {
			return &reply, nil
		}

		building.Captain5 = 0
	}

	var oldCaptainID int32
	switch req.BuildingSeat {
	case 1:

		oldCaptainID = building.Captain1
		building.Captain1 = req.CaptainID
	case 2:

		oldCaptainID = building.Captain2
		building.Captain2 = req.CaptainID
	case 3:

		oldCaptainID = building.Captain3
		building.Captain3 = req.CaptainID
	case 4:

		oldCaptainID = building.Captain4
		building.Captain4 = req.CaptainID
	case 5:

		oldCaptainID = building.Captain5
		building.Captain5 = req.CaptainID
	}

	// 未变化
	if req.CaptainID == oldCaptainID {
		return &reply, nil
	}

	// 下船逻辑
	if req.CaptainID == 0 {

		captainC.SetBuildingID(roleID, oldCaptainID, 0)

		buildingC.Save(building)

		reply.Building = building
		return &reply, nil

	}

	// 检查是否有船长数据
	captain := captainC.GetCaptain(roleID, req.CaptainID)

	if oldCaptainID > 0 {
		// 被顶掉的船长下船
		captainC.SetBuildingID(roleID, oldCaptainID, 0)
	}

	if captain.BuildingID == building.BuildingID {
		// 同一船换个位置

	} else {

		if captain.BuildingID > 0 {
			// 新上船的船长的旧船下船
			building2, err := s.removeCaptain(roleID, captain.BuildingID, captain.CaptainID)
			if err != nil {
				return &reply, err
			} else {
				reply.Building2 = building2
			}
		}

		captainC.SetBuildingID(roleID, captain.CaptainID, building.BuildingID)
	}

	buildingC.Save(building)
	reply.Building = building

	// quest
	questC.ShipCaptainNum(building)
	return &reply, nil
}

func (*BuildingService) Create(ctx context.Context, req *wrappers.Int32Value) (*pb.Building, error) {

	return buildingC.BuildingService.Create(ctx, req)
}

func (*BuildingService) GetDispatch(ctx context.Context, req *empty.Empty) (*pb.DispatchList, error) {

	return buildingC.BuildingService.GetDispatch(ctx, req)
}

func (*BuildingService) Dispatch(ctx context.Context, req *pb.DispatchRequest) (*pb.Dispatch, error) {

	return buildingC.BuildingService.Dispatch(ctx, req)
}

func (*BuildingService) FinishDispatch(ctx context.Context, req *wrappers.Int32Value) (*pb.RawItem, error) {

	return buildingC.BuildingService.FinishDispatch(ctx, req)
}

func (*BuildingService) RefreshDispatch(ctx context.Context, req *empty.Empty) (*pb.DispatchList, error) {

	return buildingC.BuildingService.RefreshDispatch(ctx, req)
}

// 新上船的船长的旧船下船 太复杂分开写
func (s *BuildingService) removeCaptain(roleID, buildingID, captainID int32) (*pb.Building, error) {

	captainC.SetBuildingID(roleID, captainID, 0)

	var building = buildingC.GetBuilding(roleID, buildingID)

	switch captainID {
	case building.Captain1:
		building.Captain1 = 0

	case building.Captain2:
		building.Captain2 = 0

	case building.Captain3:
		building.Captain3 = 0

	case building.Captain4:
		building.Captain4 = 0

	case building.Captain5:
		building.Captain5 = 0
	}

	// 被下船的船也要更新数据
	buildingC.Save(building)
	return building, nil
}
